package org.karelun.gef.dom;

import java.util.List;

import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.swt.graphics.RGB;
import org.karelun.gef.helper.DOMConstant;
import org.karelun.gef.model.AbstractConnectionModel;
import org.karelun.gef.model.AttributeModel;
import org.karelun.gef.model.ClassModel;
import org.karelun.gef.model.DiagramModel;
import org.karelun.gef.model.ImageModel;
import org.karelun.gef.model.MethodModel;
import org.karelun.gef.model.Node;
import org.karelun.gef.model.PackageModel;
import org.karelun.gef.model.RelationModel;
import org.karelun.gef.utils.ColorUtils;
import org.karelun.gef.utils.DOMUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class SaveClassDiagram {
	
	private DiagramModel diagram=null;

	public SaveClassDiagram(DiagramModel diagram) {
		this.diagram=diagram;;
	}

	public Document writeDocument() {
		Document document = DOMUtils.getDocumentBuilder().newDocument();
		writeContents(document);
		return document;
	}

	private void writeContents(Document document) {
		Element rootEle = DOMUtils.createElement(document,
				DOMConstant.TAG_classDiagram);
		rootEle.setAttribute(DOMConstant.ATTR_author, DOMConstant.author);
		writeNodes(rootEle);
		writeConnectios(rootEle);
	}

	private void writeNodes(Element element) {
		if(diagram==null)
			return;
		List<Node> nodes = diagram.getNodes();
		if (nodes == null || nodes.isEmpty())
			return;
		for (Node node : nodes) {
			String tagName=parseTagName(node);
			Element classEle = DOMUtils.createElement(element, tagName);
			writeTextAndId(classEle, node);
			writeLocation(classEle, node);
			writeSize(classEle, node);
			writeForeColor(classEle, node);
			writeBackgroundColor(classEle, node);

			if (node instanceof ClassModel) {
				ClassModel model = (ClassModel) node;
				List<AttributeModel> attrModels = model.getAttrModels();
				for(AttributeModel attrModel:attrModels){
					Element attrEle = DOMUtils.createElement(classEle,
							DOMConstant.TAG_attribute);
					writeTextAndId(attrEle, attrModel);
				}
				List<MethodModel> methodModels = model.getMethodModels();
				for(MethodModel method:methodModels){
					Element methodEle = DOMUtils.createElement(classEle, DOMConstant.TAG_method);
					writeTextAndId(methodEle, method);
				}
			}
		}
	}

	private String parseTagName(Node node) {
		if(node instanceof ClassModel)
			return DOMConstant.TAG_class;
		else if(node instanceof PackageModel)
			return DOMConstant.TAG_package;
		else if(node instanceof RelationModel)
			return DOMConstant.TAG_relation;
		else if(node instanceof ImageModel)
			return DOMConstant.TAG_image;
		return null;
	}

	private void writeTextAndId(Element classEle, Node node) {
		String name = node.getText();
		if (name != null) {
			classEle.setAttribute(DOMConstant.ATTR_name, name);
			classEle.setAttribute(DOMConstant.ATTR_id, node.getId());
		}
	}

	private void writeSize(Element classEle, Node node) {
		Dimension size = node.getSize();
		if (size != null) {
			Element sizeEle = DOMUtils.createElement(classEle,
					DOMConstant.TAG_size);
			sizeEle.setAttribute(DOMConstant.ATTR_width, String
					.valueOf(size.width));
			sizeEle.setAttribute(DOMConstant.ATTR_height, String
					.valueOf(size.height));
		}

	}

	private void writeForeColor(Element classEle, Node node) {
		RGB foreColor = node.getForeColor();
		if (foreColor != null) {
			Element foreColorEle = DOMUtils.createElement(classEle,
					DOMConstant.TAG_FORE_COLOR);
			foreColorEle.setAttribute(DOMConstant.ATTR_COLOR, ColorUtils
					.toString(foreColor));
		}
	}

	private void writeBackgroundColor(Element classEle, Node node) {
		RGB bgColor = node.getBgColor();
		if (bgColor != null) {
			Element bgColorEle = DOMUtils.createElement(classEle,
					DOMConstant.TAG_BG_COLOR);
			bgColorEle.setAttribute(DOMConstant.ATTR_COLOR, ColorUtils
					.toString(bgColor));
		}
	}

	private void writeLocation(Element classEle, Node node) {
		Point loc = node.getLocation();
		if (loc != null) {
			Element locEle = DOMUtils.createElement(classEle,
					DOMConstant.TAG_loc);
			locEle.setAttribute(DOMConstant.ATTR_x, String.valueOf(loc.x)); 
			locEle.setAttribute(DOMConstant.ATTR_y, String.valueOf(loc.y));
		}
	}

	private void writeConnectios(Element rootEle) {
		if(diagram==null)
			return ;
		List<AbstractConnectionModel> conns = diagram.getConnections();
		if (conns == null || conns.isEmpty())
			return;
		for (AbstractConnectionModel conn : conns) {
			Node sourceNode = conn.getSource();
			Node targetNode = conn.getTarget();
			if (sourceNode instanceof ClassModel
					|| targetNode instanceof ClassModel
					|| sourceNode instanceof RelationModel
					|| targetNode instanceof RelationModel) {

				Element relationEle = DOMUtils.createElement(rootEle,
						DOMConstant.TAG_connection);
				String name = conn.getName();
				relationEle.setAttribute(DOMConstant.ATTR_type, name);

				Element sourceEle = DOMUtils.createElement(relationEle,
						DOMConstant.TAG_source);
				sourceEle.setAttribute(DOMConstant.ATTR_sourceNode, sourceNode
						.getId());
				Element targetEle = DOMUtils.createElement(relationEle,
						DOMConstant.TAG_target);
				targetEle.setAttribute(DOMConstant.ATTR_targetNode, targetNode
						.getId());
			}
		}
	}
}
